#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include <iostream>

using namespace llvm;

// 定义一个简单的函数，计算 a + b
llvm::Function *createAddFunction(LLVMContext &Context, Module &M) {
  // 定义函数类型
  auto AddFuncType = FunctionType::get(Type::getDoubleTy(Context), {Type::getDoubleTy(Context), Type::getDoubleTy(Context)}, false);

  // 创建函数
  Function *AddFunc = Function::Create(AddFuncType, Function::ExternalLinkage, "add", M);

  // 添加参数
  Function::arg_iterator args = AddFunc->arg_begin();
  Value *a = &*args++; // 第一个参数
  Value *b = &*args;   // 第二个参数

  // 获取 IR 构建器
  IRBuilder<> Builder(Context);
  BasicBlock *BB = BasicBlock::Create(Context, "entry", AddFunc);
  Builder.SetInsertPoint(BB);

  // 创建 a + b 的指令
  Value *AddResult = Builder.CreateFAdd(a, b, "addResult");

  // 返回结果
  Builder.CreateRet(AddResult);

  return AddFunc;
}

int main(int argc, char **argv) {
  // 初始化 LLVM 核心库
  LLVMContext &Context = getGlobalContext();
  InitLLVM X(argc, argv);

  // 创建模块
  Module M("example", Context);

  // 创建 add 函数
  createAddFunction(Context, M);

  // 验证模块
  verifyModule(M, &errs());

  // 初始化执行引擎
  ExecutionEngine* EE = EngineBuilder(M).create();

  if (!EE) {
    cerr << "Could not create ExecutionEngine!\n";
    return 1;
  }

  // 获取 add 函数的地址
  double (*Add)(double, double) = (double (*)(double, double))EE->getPointerToFunction(AddFunc);

  // 测试 add 函数
  cout << "add(3.0, 4.0) = " << Add(3.0, 4.0) << "\n";

  // 清理
  delete EE;

  return 0;
}